/*
Copyright (C) 1994-1995 Apogee Software, Ltd.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "rt_def.h"
#include <malloc.h>
#include <dos.h>
#include <string.h>
#include "sprites.h"
#include <stdio.h>
#include <stdlib.h>
#include "rt_stat.h"
#include "z_zone.h"
#include "lumpy.h"
#include "rt_util.h"
#include "rt_draw.h"
#include "rt_ted.h"
#include "rt_door.h"
#include "rt_main.h"
#include "w_wad.h"
#include "rt_main.h"
#include "rt_rand.h"
#include "rt_menu.h"
#include "rt_sound.h"
#include "_rt_stat.h"
#include "rt_net.h"
#include "rt_view.h"
#include "isr.h"
//MED
#include "memcheck.h"



/*
=============================================================================

Global Variables                                                                                                                                 GLOBAL VARIABLES

=============================================================================
*/

statobj_t   *firstactivestat,*lastactivestat;
statobj_t   *firstemptystat,*lastemptystat;

wall_t      switches[MAXSWITCHES],*lastswitch;
respawn_t   *firstrespawn,*lastrespawn;
statobj_t	*FIRSTSTAT,*LASTSTAT,*sprites[MAPSIZE][MAPSIZE];
animwall_t  animwalls[MAXANIMWALLS];

dirtype opposite[9] =
	{west,southwest,south,southeast,east,northeast,north,northwest,nodir};






statinfo stats[NUMSTATS] =
{
{0,SPR0_YLIGHT, stat_ylight,FL_LIGHT|FL_SHOOTABLE,0,0,2},
{0,SPR1_RLIGHT, stat_rlight,FL_LIGHT|FL_SHOOTABLE,0,0,2},
{0,SPR2_GLIGHT, stat_glight,FL_LIGHT|FL_SHOOTABLE,0,0,2},
{0,SPR3_BLIGHT, stat_blight,FL_LIGHT|FL_SHOOTABLE,0,0,2},
{0,SPR4_CHAND, stat_chandelier,FL_LIGHT|FL_SHOOTABLE,0,0,2},
{0,SPR5_LAMPOFF, stat_lamp,FL_LIGHT|FL_BLOCK|FL_SHOOTABLE,0,0,2},
{0,SPR73_GKEY1, stat_pedgoldkey,FL_COLORED|FL_BONUS|FL_CHANGES|FL_BLOCK|FL_ACTIVE,2,16,pc_orange},
{0,SPR73_GKEY1,stat_pedsilverkey,FL_COLORED|FL_BONUS|FL_CHANGES|FL_BLOCK|FL_ACTIVE,2,16,pc_gray},
{0,SPR73_GKEY1, stat_pedironkey,FL_COLORED|FL_BONUS|FL_CHANGES|FL_BLOCK|FL_ACTIVE,2,16,pc_olive},
{0,SPR73_GKEY1,stat_pedcrystalkey,FL_COLORED|FL_BONUS|FL_CHANGES|FL_BLOCK|FL_ACTIVE,2,16,pc_red},
{0,SPR6_GIBS1,  stat_gibs1},
{0,SPR7_GIBS2,  stat_gibs2},
{0,SPR8_GIBS3,  stat_gibs3},
{0,SPR9_MONKMEAL, stat_monkmeal,FL_BONUS|FL_RESPAWN},
{0,PORRIDGE1, stat_priestporridge,FL_BONUS|FL_RESPAWN,2,6},
{0,MONKCRYSTAL11,stat_monkcrystal1,FL_BONUS|FL_ACTIVE|FL_RESPAWN,2,6},
{0,MONKCRYSTAL21,stat_monkcrystal2,FL_BONUS|FL_ACTIVE|FL_RESPAWN,2,7},
{0,ONEUP01,stat_oneup,FL_BONUS|FL_ACTIVE|FL_FULLLIGHT,2,8},
{0,THREEUP01,stat_threeup,FL_BONUS|FL_ACTIVE|FL_FULLLIGHT,2,8},
{0,TORCH1,stat_altbrazier1,FL_HEAT|FL_BLOCK|FL_ACTIVE|FL_LIGHT|FL_SHOOTABLE,2,15,2},
{0,SPR_ABRAZIER2,stat_altbrazier2,FL_HEAT|FL_BLOCK|FL_LIGHT|FL_SHOOTABLE,0,0,2},
{0,FBASIN1,stat_healingbasin,FL_BONUS|FL_CHANGES|FL_ACTIVE|FL_BLOCK,2,3},
{20,EBASIN,stat_emptybasin,FL_BLOCK|FL_SHOOTABLE,},
{0,BAT1,stat_bat,FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_WEAPON,1,16,0,0,10},
{0,KNIFE_STATUE1,stat_knifestatue,FL_BONUS|FL_CHANGES|FL_BLOCK},
{0,SPR_TWOPIST,stat_twopistol,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,5},
{0,SPR_MP40,stat_mp40,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,5},
{0,SPR_BAZOOKA,stat_bazooka,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,10},
{0,SPR_FIREBOMB,stat_firebomb,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,5},
{0,SPR_HEATSEEK,stat_heatseeker,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,7},
{0,SPR_DRUNK,stat_drunkmissile,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,7},
{0,SPR_FIREWALL,stat_firewall,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,5},
{0,SPR_SPLIT,stat_splitmissile,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,7},
{0,SPR_KES,stat_kes,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,7},
{0,LIFEITEMA01,stat_lifeitem1,FL_BONUS|FL_ACTIVE|FL_SHOOTABLE|FL_FULLLIGHT,2,8, 2},
{0,LIFEITEMB01,stat_lifeitem2,FL_BONUS|FL_ACTIVE|FL_SHOOTABLE|FL_FULLLIGHT,2,8, 2},
{0,LIFEITEMD01,stat_lifeitem3,FL_BONUS|FL_ACTIVE|FL_SHOOTABLE|FL_FULLLIGHT,2,8, 2},
{0,LIFEITEMC01,stat_lifeitem4,FL_BONUS|FL_ACTIVE|FL_SHOOTABLE|FL_FULLLIGHT,2,15, 2},
{24,SPR32_EXPLOS,stat_tntcrate,FL_SHOOTABLE|FL_BLOCK|FL_WOODEN,0,0,3,10},
{12,SPR33_CBARREL,stat_bonusbarrel,FL_METALLIC|FL_SHOOTABLE|FL_BLOCK,0,0,3,10},
{0,TORCH1,stat_torch,FL_BLOCK|FL_LIGHT|FL_ACTIVE|FL_HEAT|FL_SHOOTABLE,2,15,2},
{30,FFLAME1,stat_floorfire,FL_HEAT|FL_BLOCK|FL_LIGHT|FL_ACTIVE|FL_SHOOTABLE,2,7,30},
{0,DIP11,stat_dipball1,FL_BONUS|FL_FULLLIGHT},
{0,DIP21,stat_dipball2,FL_BONUS|FL_FULLLIGHT},
{0,DIP31,stat_dipball3,FL_BONUS|FL_FULLLIGHT},
{0,SPR34_TOUCH1,stat_touch1,0|FL_TRANSLUCENT|FL_FADING},
{0,SPR35_TOUCH2,stat_touch2,0|FL_TRANSLUCENT|FL_FADING},
{0,SPR36_TOUCH3,stat_touch3,0|FL_TRANSLUCENT|FL_FADING},
{0,SPR37_TOUCH4,stat_touch4,0|FL_TRANSLUCENT|FL_FADING},
{20,SPR62_ETOUCH1,stat_dariantouch,FL_METALLIC|FL_BANDF|FL_SHOOTABLE|FL_BLOCK,10,3,50},
{0,SCOTHEAD1, stat_scotthead,FL_BONUS|FL_ACTIVE|FL_FULLLIGHT,4,7},

{0,SPR38_GARBAGE1,stat_garb1},
{0,SPR39_GARBAGE2,stat_garb2},
{0,SPR40_GARBAGE3,stat_garb3},

{0,SPR41_SHIT,stat_shit},
{0,SPR42_GRATE,stat_grate},
{0,SPR43_MSHARDS,stat_metalshards},
{20,SPR44_PEDESTAL,stat_emptypedestal,FL_BLOCK|FL_SHOOTABLE|FL_WOODEN,0,0,60},
{20,SPR45_ETABLE,stat_emptytable,FL_BLOCK|FL_SHOOTABLE|FL_WOODEN,0,0,100},
{16,SPR46_STOOL,stat_stool,FL_BLOCK|FL_SHOOTABLE|FL_WOODEN,0,0,25},
{0,SPR_PUSHCOLUMN1,stat_bcolumn,FL_BLOCK|FL_HEIGHTFLIPPABLE},
{0,SPR_PUSHCOLUMN1,stat_gcolumn,FL_BLOCK|FL_HEIGHTFLIPPABLE},
{0,SPR_PUSHCOLUMN1,stat_icolumn,FL_BLOCK|FL_HEIGHTFLIPPABLE},
{20,SPR50_TREE,stat_tree,FL_SHOOTABLE|FL_BLOCK},
{20,SPR51_PLANT,stat_plant,FL_SHOOTABLE|FL_BLOCK},
{20,BLUEVASE,stat_urn,FL_SHOOTABLE|FL_BLOCK},
{0,SPR54_HAY,stat_haystack,FL_SHOOTABLE|FL_BLOCK,0,0,20},
{12,SPR55_IBARREL,stat_ironbarrel,FL_METALLIC|FL_BLOCK|FL_SHOOTABLE,0,0,50},
{0,HGRATE1,stat_heatgrate,FL_LIGHT|FL_ACTIVE,2,4,0,5},
{-10,STNPOLE1,stat_standardpole,FL_SHOOTABLE|FL_BLOCK,0,0,25},
{0,PREPIT,stat_pit,FL_CHANGES},
{0,GODPOWERUP1,stat_godmode,FL_WEAPON|FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8},
{0,DOGPOWERUP1,stat_dogmode,FL_WEAPON|FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8},
{0,FLEETFEETPOWERUP1,stat_fleetfeet,FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8},
{0,ELASTICPOWERUP1, stat_elastic, FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8},
{0,MUSHROOMPOWERUP1, stat_mushroom, FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8},
{0,GASMASKPOWERUP, stat_gasmask, FL_BONUS|FL_RESPAWN},
{0,BULLETPROOFPOWERUP, stat_bulletproof, FL_BONUS|FL_RESPAWN},
{0,ASBESTOSPOWERUP, stat_asbesto, FL_BONUS|FL_RESPAWN},
{0,RANDOMPOWERUP1, stat_random, FL_BONUS|FL_ACTIVE|FL_RESPAWN,2,8},
{0,RUBBLE1, stat_rubble, FL_ACTIVE,2,10},
{0,WOODFRAG1, stat_woodfrag, FL_ACTIVE,2,14},
{0,ROBOGRDDIE1, stat_metalfrag, FL_ACTIVE,2,10},
{0,EMPTY_STATUE1,stat_emptystatue,FL_BLOCK|FL_SHOOTABLE,0,0,50},
{16,TOMLARVA1,stat_tomlarva,FL_ACTIVE|FL_SHOOTABLE|FL_BLOCK,2,4,150},
{0,BULLETHOLE,stat_bullethole,FL_TRANSLUCENT},
//MED
//{0,COLLECTOR1,stat_collector,FL_ACTIVE|FL_BONUS,2,8,-1},
{0,DOPE1,stat_collector,FL_ACTIVE|FL_BONUS,2,8,-1},
{0,SPR_MINE1,stat_mine,FL_BONUS|FL_SHOOTABLE|FL_RESPAWN,0,0,10},
{0,MISSMOKE1,stat_missmoke,FL_ACTIVE,6,4},
{0,PLATFORM1,stat_disk,FL_BLOCK|FL_HEIGHTFLIPPABLE},
{-1}
};


dirtype diagonal[9][9] =
{
/* east */  {nodir,nodir,northeast,nodir,nodir,nodir,southeast,nodir,nodir},
			{nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
/* north */ {northeast,nodir,nodir,nodir,northwest,nodir,nodir,nodir,nodir},
			{nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
/* west */  {nodir,nodir,northwest,nodir,nodir,nodir,southwest,nodir,nodir},
			{nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
/* south */ {southeast,nodir,nodir,nodir,southwest,nodir,nodir,nodir,nodir},
			{nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
			{nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}
};

/*
=============================================================================

Local Variables                                                                                                                                 GLOBAL VARIABLES

=============================================================================
*/
static awallinfo_t animwallsinfo[MAXANIMWALLS] =
  {{3,4,"FPLACE1\0"}, //lava wall
   {3,6,"ANIMY1\0"}, //anim red
   {3,6,"ANIMR1\0"}, //anim yellow
   {40,4,"ANIMFAC1\0"}, //anim face
   {3,4,"ANIMONE1\0"}, //anim one
   {3,4,"ANIMTWO1\0"}, //anim two
   {3,4,"ANIMTHR1\0"}, //anim three
   {3,4,"ANIMFOR1\0"}, //anim four
   {3,6,"ANIMGW1\0"}, //anim grey water
   {3,6,"ANIMYOU1\0"}, //anim you do not belong
   {3,6,"ANIMBW1\0"}, //anim brown water
   {3,6,"ANIMBP1\0"}, //anim brown piston
   {3,6,"ANIMCHN1\0"}, //anim chain
   {3,6,"ANIMFW1\0"}, //anim firewall
   {3,6,"ANIMLAT1\0"}, //anim little blips
   {3,6,"ANIMST1\0"}, //anim light streams left
   {3,6,"ANIMRP1\0"}};//anim light streams right

int statcount;


void AddToFreeStaticList(statobj_t*stat)
{ if (!firstemptystat)
	 firstemptystat = stat;
  else
	 {stat->statprev = lastemptystat;
	  lastemptystat->statnext = stat;
	 }
  lastemptystat = stat;

}


void RemoveFromFreeStaticList(statobj_t*stat)
{
  if (stat == lastemptystat)
		lastemptystat = stat->statprev;
  else
		stat->statnext->statprev = stat->statprev;

  if (stat == firstemptystat)
		firstemptystat = stat->statnext;
  else
		stat->statprev->statnext = stat->statnext;

  stat->statprev = NULL;
  stat->statnext = NULL;

}




/*
===============
=
= MakeStatActive
=
===============
*/

void MakeStatActive(statobj_t*x)
 {if (!firstactivestat)
	 firstactivestat	= x;
  else
	  {x->prevactive = lastactivestat;
		lastactivestat->nextactive = x;
	  }
  lastactivestat = x;
 }


/*
===============
=
= MakeStatInactive
=
===============
*/

void MakeStatInactive(statobj_t*stat)
{
 if (stat == lastactivestat)
	lastactivestat = stat->prevactive;
 else
	stat->nextactive->prevactive = stat->prevactive;

 if (stat == firstactivestat)
	firstactivestat = stat->nextactive;
 else
	stat->prevactive->nextactive = stat->nextactive;

 stat->prevactive = NULL;
 stat->nextactive = NULL;

}
/*
===============
=
= AddStatic
=
===============
*/

void AddStatic(statobj_t *stat)
 {if (FIRSTSTAT)
	 {stat->statprev = LASTSTAT;
	  LASTSTAT->statnext = stat;
	 }
  else
	 FIRSTSTAT = stat;
  LASTSTAT = stat;
 }



void RemoveStatic(statobj_t*stat)
{
   if (stat->flags & FL_ABP) //remove from active list
      MakeStatInactive(stat);

   if (stat == LASTSTAT)     // remove from master list
      LASTSTAT = stat->statprev;
   else
      stat->statnext->statprev = stat->statprev;

   if (stat == FIRSTSTAT)
      FIRSTSTAT = stat->statnext;
   else
      stat->statprev->statnext = stat->statnext;

   stat->statprev = NULL;
   stat->statnext = NULL;

   if (stat->flags & FL_WEAPON)
      MISCVARS->NUMWEAPONS --;

   if ((stat->flags & FL_RESPAWN) &&
       gamestate.BattleOptions.RespawnItems &&
       (!((stat->flags & FL_WEAPON ) &&
          (gamestate.BattleOptions.WeaponPersistence)
         )
       )
      )
      {
      respawn_t*temp;
   //    if ( !( (stat->flags & FL_WEAPON) &&
   //          (MISCVARS->NUMWEAPONS >= (numplayers+10))
      //      )
      // )
         {
         temp = (respawn_t*)Z_LevelMalloc(sizeof(respawn_t),PU_LEVELSTRUCT,NULL);

         memset (temp,0,sizeof(*temp));
         temp->ticcount = GetRespawnTimeForItem(stat->itemnumber);
         temp->tilex = stat->tilex;
         temp->tiley = stat->tiley;
         temp->itemnumber = stat->itemnumber;
         temp->spawnz = stat->z;
         temp->linked_to = stat->linked_to;
         //SoftError("\nrespawn obj created for stattype %d with z = %d",stat->itemnumber,temp->spawnz);
         AddRespawnStatic(temp);
         }
      }
   //Z_Free(stat);
   AddToFreeStaticList(stat);

   //Add_To_Delete_Array(stat);
   statcount --;
   }


void RemoveRespawnStatic(respawn_t*stat)
{
	if (stat == lastrespawn)
		lastrespawn = stat->prev;
	else
		stat->next->prev = stat->prev;

	if (stat == firstrespawn)
		firstrespawn = stat->next;
	else
		stat->prev->next = stat->next;

	stat->prev = NULL;
	stat->next = NULL;
	Z_Free(stat);
}


void TurnOffLight(int tilex,int tiley)
{
  DoLights(tilex,tiley);
  LightsInArea[MAPSPOT(tilex,tiley,0)-AREATILE]--;

}


void ActivateLight(int light)
{statobj_t*tstat;

 tstat = (statobj_t*)light;

 tstat->shapenum ++;
 tstat->flags |= FL_LIGHTON;
 TurnOnLight(tstat->tilex,tstat->tiley);

}


void DeactivateLight(int light)
{statobj_t*tstat;

 tstat = (statobj_t*)light;

 tstat->shapenum --;
 tstat->flags &= ~(FL_LIGHTON);
 TurnOffLight(tstat->tilex,tstat->tiley);

}

void TurnOnLight(int i,int j)
{

 LightsInArea[MAPSPOT(i,j,0)-AREATILE]++;

 if (lightsource==0)
    return;

 if ((!(tilemap[i+1][j])) && (!(tilemap[i-1][j])))
	{
	SetLight(i,j,0xcdeffedc);
	SetLight(i+1,j,0x135789ab);
	SetLight(i-1,j,0xba987351);
	SetLight(i,j+1,0xcdeffedc);
	SetLight(i,j-1,0xcdeffedc);
	SetLight(i-1,j-1,0xba987351);
	SetLight(i+1,j+1,0xba987351);
	SetLight(i+1,j-1,0x135789ab);
	SetLight(i-1,j+1,0x135789ab);
	}
 else if ((!(tilemap[i][j+1])) && (!(tilemap[i][j-1])))
	{
	SetLight(i,j,0xcdeffedc);
	SetLight(i+1,j,0xcdeffedc);
	SetLight(i-1,j,0xcdeffedc);
	SetLight(i,j+1,0x135789ab);
	SetLight(i,j-1,0xba987531);
	SetLight(i-1,j-1,0x135789ab);
	SetLight(i+1,j-1,0xba987531);
	SetLight(i+1,j+1,0x135789ab);
	SetLight(i-1,j+1,0xba987531);
	}
					//  |
					//__|
 else if ((tilemap[i][j+1]) && (tilemap[i+1][j]))
	{
	SetLight(i,j,0xcdeffedc);
	SetLight(i+1,j,0xcdeffedc);
	SetLight(i-1,j,0xcdeffedc);
	SetLight(i,j+1,0xcdeffedc);
	SetLight(i,j-1,0xcdeffedc);
	SetLight(i-1,j-1,0xba987351);
	SetLight(i+1,j-1,0xba987351);
	SetLight(i+1,j+1,0xba987351);
	SetLight(i-1,j+1,0x135789ab);
	}
					//|
					//|_
 else if ((tilemap[i][j+1]) && (tilemap[i-1][j]))
	{
	SetLight(i,j,0xcdeffedc);
	SetLight(i+1,j,0xcdeffedc);
	SetLight(i-1,j,0xcdeffedc);
	SetLight(i,j+1,0xcdeffedc);
	SetLight(i,j-1,0xcdeffedc);
	SetLight(i-1,j-1,0x135789ab);
	SetLight(i+1,j-1,0xba987531);
	SetLight(i+1,j+1,0xba987531);
	SetLight(i-1,j+1,0xba987531);
	}
					//_
					// |
 else if ((tilemap[i][j-1]) && (tilemap[i+1][j]))
	{
	SetLight(i,j,0xcdeffedc);
	SetLight(i+1,j,0xcdeffedc);
	SetLight(i-1,j,0xcdeffedc);
	SetLight(i,j+1,0xcdeffedc);
	SetLight(i,j-1,0xcdeffedc);
	SetLight(i-1,j-1,0xba987531);
	SetLight(i+1,j-1,0x135789ab);
	SetLight(i+1,j+1,0x135789ab);
	SetLight(i-1,j+1,0xba987531);
	}
					//__
					//|
 else if ((tilemap[i][j-1]) && (tilemap[i-1][j]))
	{
	SetLight(i,j,0xcdeffedc);
	SetLight(i+1,j,0xcdeffedc);
	SetLight(i-1,j,0xcdeffedc);
	SetLight(i,j+1,0xcdeffedc);
	SetLight(i,j-1,0xcdeffedc);
	SetLight(i-1,j-1,0x135789ab);
	SetLight(i+1,j-1,0x135789ab);
	SetLight(i+1,j+1,0xba987531);
	SetLight(i-1,j+1,0xba987531);
	}
 else if (tilemap[i][j])
	{
	SetLight(i,j,0x58bffb85);
	}
 else
	{
	SetLight(i,j,0xcdeffedc);
	SetLight(i+1,j,0xba987654);
	SetLight(i-1,j,0x456789ab);
	SetLight(i,j+1,0xba987654);
	SetLight(i,j-1,0x456789ab);
	SetLight(i-1,j+1,0x33322211);
	SetLight(i+1,j+1,0x33322211);
	SetLight(i+1,j-1,0x11222333);
	SetLight(i-1,j-1,0x11222333);
	}


}




/*===============
=
= AddRespawnStatic
=
===============
*/

void AddRespawnStatic(respawn_t*stat)
 {
  if (firstrespawn)
	{stat->prev = lastrespawn;
	 lastrespawn->next = stat;
	}
  else
	firstrespawn = stat;
  lastrespawn = stat;
 }


/*
===============
=
= InitStaticList
=
===============
*/

void InitStaticList (void)
{
	FIRSTSTAT = NULL;
	LASTSTAT = NULL;
	lastactivestat = NULL;
	firstactivestat = NULL;
	firstrespawn = NULL;
	lastrespawn = NULL;
	lastemptystat = NULL;
	firstemptystat = NULL;

	memset(&BulletHoles[0],0,sizeof(BulletHoles));
   MISCVARS->BulletHoleNum = 0;


	memset(sprites,0,sizeof(sprites));
	if (loadedgame==false)
		{
		memset(switches,0,sizeof(switches));
		lastswitch = &switches[0];
		}
	statcount = 0;

}


/*
===============
=
= InitAnimatedWallList
=
===============
*/

void InitAnimatedWallList(void)
{
 int i;

 for (i=0;i<MAXANIMWALLS;i++)
	 animwalls[i].active=0;
}

/*
===============
=
= SetupAnimatedWall
=
===============
*/

void SetupAnimatedWall(int which)
{
   animwall_t * aw;
   int i;
   int texture;

   aw = &animwalls[which];

   aw->active=1;
   aw->ticcount=animwallsinfo[which].tictime;
   aw->count = 1;

   texture=W_GetNumForName(animwallsinfo[which].firstlump);

   aw->basetexture=texture;
   aw->texture=texture;

   if (DoPanicMapping()==true)
      {
      PreCacheLump(aw->basetexture,PU_CACHEWALLS);
      }
   else
      {
      for (i=aw->basetexture;i<aw->basetexture+animwallsinfo[which].numanims;i++)
         PreCacheLump(i,PU_CACHEWALLS);
      }
}


/*
===============
=
= SaveStatics
=
===============
*/

void SaveStatics (byte **buffer, int * size)
{statobj_t * temp;
 saved_stat_type dummy;
 byte * tptr;
 int count;

 if (statcount==0)
	 {
	 *size=0;
	 *buffer=SafeMalloc(16);
	 return;
	 }
 *size = statcount*sizeof(saved_stat_type);
 *buffer = (byte *)SafeMalloc(*size);
 tptr = *buffer;

 for(count=0,temp=FIRSTSTAT;temp;temp=temp->statnext)
  {dummy.x = temp->x;
	dummy.y = temp->y;
	dummy.z = temp->z;
	dummy.flags = temp->flags;
	dummy.ticcount = temp->ticcount;
	dummy.hitpoints = temp->hitpoints;
	dummy.shapenum = temp->shapenum;
	dummy.ammo = temp->ammo;
	dummy.count = temp->count;
	dummy.numanims = temp->numanims;
	dummy.itemnumber = temp->itemnumber;
	dummy.areanumber = temp->areanumber;
	temp->whichstat = count;
	dummy.whichstat = count++;
	dummy.linked_to = temp->linked_to;

	memcpy(tptr,&(dummy.x),sizeof(saved_stat_type));
	tptr += sizeof(saved_stat_type);

  }

}

/*
===============
=
= DoLights
=
===============
*/

void DoLights (int tilex, int tiley)
{
    if (lightsource==0)
       return;
	 if (TurnOffLight0 (tilex, tiley))
       LightSourceAt(tilex,tiley) = 0;

	 if (TurnOffLight1 (tilex, tiley, -1, -1))
       LightSourceAt(tilex-1,tiley-1) = 0;

	 if (TurnOffLight2 (tilex, tiley, -1))
       LightSourceAt(tilex,tiley-1) = 0;

	 if (TurnOffLight1 (tilex, tiley, 1, -1))
       LightSourceAt(tilex+1,tiley-1) = 0;

	 if (TurnOffLight3 (tilex, tiley, 1))
       LightSourceAt(tilex+1,tiley) = 0;

	 if (TurnOffLight1 (tilex, tiley, 1, 1))
       LightSourceAt(tilex+1,tiley+1) = 0;

	 if (TurnOffLight2 (tilex, tiley, 1))
       LightSourceAt(tilex,tiley+1) = 0;

	 if (TurnOffLight1 (tilex, tiley, -1, 1))
       LightSourceAt(tilex-1,tiley+1) = 0;

	 if (TurnOffLight3 (tilex, tiley, -1))
       LightSourceAt(tilex-1,tiley) = 0;
}


/*
===============
=
= TurnOffLight0
=
===============
*/

boolean TurnOffLight0 (int tilex, int tiley)
{
   if ( IsLight(tilex-1,tiley  ) ||
        IsLight(tilex-1,tiley-1) ||
        IsLight(tilex  ,tiley-1) ||
        IsLight(tilex+1,tiley-1) ||
        IsLight(tilex+1,tiley  ) ||
        IsLight(tilex+1,tiley+1) ||
        IsLight(tilex  ,tiley+1) ||
		  IsLight(tilex-1,tiley+1) )
		return (false);
	else
		return (true);
}

/*
===============
=
= TurnOffLight1
=
===============
*/

boolean TurnOffLight1 (int tilex, int tiley, int i, int j)
{
	int tempi = 2*i;
	int tempy = 2*j;

   if ( IsLight(tilex+i    ,tiley  ) ||
        IsLight(tilex+i    ,tiley+j) ||
        IsLight(tilex      ,tiley+j) ||
        IsLight(tilex      ,tiley+tempy) ||
        IsLight(tilex+i    ,tiley+tempy) ||
        IsLight(tilex+tempi,tiley+tempy) ||
        IsLight(tilex+tempi,tiley+j) ||
	     IsLight(tilex+tempi,tiley))
		return (false);
	else
		return (true);
}


/*
===============
=
= TurnOffLight2
=
===============
*/

boolean TurnOffLight2 (int tilex, int tiley, int j)
{
	int tempy = 2*j;

   if ( IsLight(tilex-1    ,tiley  ) ||
        IsLight(tilex-1    ,tiley+j) ||
        IsLight(tilex-1    ,tiley+tempy) ||
        IsLight(tilex      ,tiley+j) ||
        IsLight(tilex      ,tiley+tempy) ||
        IsLight(tilex+1    ,tiley) ||
        IsLight(tilex+1    ,tiley+j) ||
	     IsLight(tilex+1    ,tiley+tempy))
		return (false);
	else
		return (true);
}


/*
===============
=
= TurnOffLight3
=
===============
*/

boolean TurnOffLight3 (int tilex, int tiley, int i)
{
	int tempx = 2*i;

   if ( IsLight(tilex      ,tiley-1) ||
        IsLight(tilex+1    ,tiley-1) ||
        IsLight(tilex+tempx,tiley-1) ||
        IsLight(tilex+i    ,tiley) ||
        IsLight(tilex+tempx,tiley) ||
        IsLight(tilex      ,tiley+1) ||
        IsLight(tilex+i    ,tiley+1) ||
	     IsLight(tilex+tempx,tiley+1))
		return (false);
	else
		return (true);
}




/*
======================
=
= PreCacheStaticFrames
=
======================
*/




void PreCacheStaticFrames(statobj_t*temp)
   {
   int z,start,stop;
   int female=0,black=0;

   PreCacheLump(temp->shapenum+shapestart,PU_CACHESPRITES);
   for (z=0;z<temp->numanims;z++)
      PreCacheLump(temp->shapenum+shapestart+z,PU_CACHESPRITES);

   if (temp->flags & FL_ROTATING)
      {
      for (z=1;z<8;z++)
         PreCacheLump(temp->shapenum+shapestart+z,PU_CACHESPRITES);
      }

   if (temp->flags & FL_WOODEN)
      {
      start = W_GetNumForName("WFRAG1");
      stop = W_GetNumForName("WFRAG14");
      PreCacheGroup(start,stop);
      }

   if (temp->flags & FL_METALLIC)
      {
      PreCacheLump(W_GetNumForName("MSHARDS"),PU_CACHESPRITES);
      start = W_GetNumForName("ROBODIE1");
      stop = W_GetNumForName("ROBODEAD");
      PreCacheGroup(start,stop);
      }

   female = ((locplayerstate->player == 1) || (locplayerstate->player == 3));
   black = (locplayerstate->player == 2);

   if (female)
      {
      start = W_GetNumForName("FPIST11");
      stop = W_GetNumForName("FPIST13");
      }
   else if (black)
      {
      start = W_GetNumForName("BMPIST1");
      stop = W_GetNumForName("BMPIST3");
      }
   else
      {
      start = W_GetNumForName("MPIST11");
      stop = W_GetNumForName("MPIST13");
		}

   PreCacheGroup(start,stop);

   switch (temp->itemnumber)
      {

      case stat_pedgoldkey:
      case stat_pedsilverkey:
      case stat_pedironkey:
      case stat_pedcrystalkey:
         PreCacheLump(W_GetNumForName("PEDESTA"),PU_CACHESPRITES);
         break;

      case stat_bat:
         start = W_GetNumForName("EXBAT1");
         stop = W_GetNumForName("EXBAT7");
         PreCacheGroup(start,stop);
         break;
      case stat_knifestatue:
         start = W_GetNumForName("KNIFE1");
         stop = W_GetNumForName("KNIFE10");
         PreCacheGroup(start,stop);
         break;
      case stat_twopistol:
         if (female)
            {
            start = W_GetNumForName("RFPIST1");
            stop = W_GetNumForName("LFPIST3");
            }
         else if (black)
            {
            start = W_GetNumForName("RBMPIST1");
            stop = W_GetNumForName("LBMPIST3");
            }
         else
            {
            start = W_GetNumForName("RMPIST1");
            stop = W_GetNumForName("LMPIST3");
            }
         PreCacheGroup(start,stop);
         break;
      case stat_mp40:
         start = W_GetNumForName("MP401");
         stop = W_GetNumForName("MP403");
         PreCacheGroup(start,stop);
         break;
      case stat_bazooka:
         start = W_GetNumForName("BAZOOKA1");
         stop = W_GetNumForName("BAZOOKA4");
         PreCacheGroup(start,stop);
         break;
      case stat_firebomb:
         start = W_GetNumForName("FBOMB1");
         stop = W_GetNumForName("FBOMB4");
         PreCacheGroup(start,stop);
         break;
      case stat_heatseeker:
         start = W_GetNumForName("HSEEK1");
         stop = W_GetNumForName("HSEEK4");
         PreCacheGroup(start,stop);
         break;
      case stat_drunkmissile:
         start = W_GetNumForName("DRUNK1");
         stop = W_GetNumForName("DRUNK4");
         PreCacheGroup(start,stop);
         break;
      case stat_firewall:
         start = W_GetNumForName("FIREW1");
         stop = W_GetNumForName("FIREW3");
         PreCacheGroup(start,stop);
         break;
      case stat_splitmissile:
         start = W_GetNumForName("SPLIT1");
         stop = W_GetNumForName("SPLIT4");
         PreCacheGroup(start,stop);
         break;
      case stat_kes:
         start = W_GetNumForName("KES1");
         stop = W_GetNumForName("KES6");
         PreCacheGroup(start,stop);
         break;
      case stat_godmode:
         start = W_GetNumForName("GODHAND1");
         stop = W_GetNumForName("GODHAND8");
         PreCacheGroup(start,stop);

         PreCacheGroup(W_GetNumForName("VAPO1"),
                       W_GetNumForName("LITSOUL"));

         PreCacheGroup(W_GetNumForName("GODFIRE1"),
                       W_GetNumForName("GODFIRE4"));

         break;
      case stat_dogmode:
         start = W_GetNumForName("DOGNOSE1");
         stop = W_GetNumForName("DOGPAW4");
         PreCacheGroup(start,stop);
         break;
      }



   }



/*
===============
=
= LoadStatics
=
===============
*/




void LoadStatics( byte * buffer, int size)
{saved_stat_type dummy;
 int stcount,i;
 statobj_t*temp;

 stcount = size/sizeof(saved_stat_type);
 InitStaticList();

 for(i=0;i<stcount;i++)
	{
	temp = (statobj_t*)Z_LevelMalloc(sizeof(statobj_t),PU_LEVELSTRUCT,NULL);
	if (!temp)
		Error("LoadStatics: Failed on allocation of static %ld of %ld",i,stcount);
	memset(temp,0,sizeof(*temp));
	memcpy(&(dummy.x),buffer,sizeof(saved_stat_type));
	temp->whichstat = statcount++;
	temp->x = dummy.x;
	temp->y = dummy.y;
	temp->z = dummy.z;
	temp->flags = dummy.flags;
	temp->ticcount = dummy.ticcount;
	temp->hitpoints = dummy.hitpoints;
	temp->shapenum = dummy.shapenum;
	temp->ammo = dummy.ammo;
	temp->count = dummy.count;
	temp->numanims = dummy.numanims;
	temp->itemnumber = dummy.itemnumber;
	temp->areanumber = dummy.areanumber;
	temp->linked_to = dummy.linked_to;

	temp->which = SPRITE;
	temp->tilex = temp->x >> TILESHIFT;
	temp->tiley = temp->y >> TILESHIFT;
	temp->flags &= ~FL_ABP;
	temp->visspot = &spotvis[temp->tilex][temp->tiley];

	if ((temp->itemnumber >= stat_touch1) &&
		 (temp->itemnumber <= stat_touch4))
	  {touchindices[temp->tilex][temp->tiley] = lasttouch + 1;
		lasttouch ++;
		SD_PreCacheSoundGroup(SD_TOUCHPLATESND,SD_BADTOUCHSND);
	  }

	AddStatic(temp);
	if (temp->shapenum != -1)
	  {
     if (temp->itemnumber == stat_bullethole)
		  {
		  SetupBulletHoleLink(temp->linked_to,temp);
		  }

	  else if (temp->flags & FL_DEADBODY)
		  {
        if ( actorat[temp->tilex][temp->tiley] == NULL )
           actorat[temp->tilex][temp->tiley] = temp;
		  }

	  else if (!(temp->flags & FL_NONMARK))
		  {
		  sprites[temp->tilex][temp->tiley] = temp;
		  }

     PreCacheStaticFrames(temp);


	  }
	PreCacheStaticSounds(temp->itemnumber);

	buffer += sizeof(saved_stat_type);
  }
}


void Set_NewZ_to_MapValue(fixed *newz,int zoffset,const char*errorstr,int tilex,int tiley)
   {
   int zf,z;

   zoffset&=0xff;
   z=zoffset>>4;
   zf=zoffset&0xf;
   if (z==0xf)
      *newz = nominalheight+64-(zf<<2);
   else
      {
      if (z>levelheight)
         Error ("You specified a height of %lx for the %s at tilex=%ld tiley=%ld when\n the level is only %ld high\n",
                 zoffset,errorstr,tilex,tiley,levelheight);
      else
         *newz = nominalheight-(z<<6)-(zf<<2);
      }

   }



/*
===============
=
= SpawnStatic
=
===============
*/




void SpawnStatic (int tilex, int tiley, int mtype, int zoffset)
{statobj_t * temp;
 boolean onetimer;



#if (SHAREWARE == 1)
   switch(mtype)
      {
      case stat_rlight:
      case stat_glight:
      case stat_ylight:
      case stat_chandelier:
         mtype = stat_blight;
         break;

      case stat_garb1:
      case stat_garb2:
      case stat_garb3:
      case stat_shit:
         mtype = stat_metalshards;
         break;

      case stat_lamp:
         mtype = stat_altbrazier2;
         break;

      }
#endif



   if ( BATTLEMODE )
      {
      if ( !gamestate.BattleOptions.SpawnWeapons )
         {
         if ( stats[ mtype ].flags & FL_WEAPON )
            {
            return;
            }
         }

      if (mtype == stat_pit)
         return;

      // Change lifeitems and extra lives to health
      switch( mtype )
         {
         case stat_lifeitem1 :
         case stat_lifeitem2 :
            mtype = stat_monkcrystal1;
            break;

         case stat_lifeitem3 :
         case stat_lifeitem4 :
         case stat_oneup :
         case stat_threeup :
            mtype = stat_monkcrystal2;
            break;
         }

      switch( mtype )
         {
         case stat_monkmeal :
         case stat_priestporridge :
         case stat_monkcrystal1 :
         case stat_monkcrystal2 :
         case stat_healingbasin :
            if ( ( gamestate.Product != ROTT_SHAREWARE ) &&
               ( gamestate.BattleOptions.SpawnMines ) &&
               ( !IsPlatform( tilex, tiley ) &&
               ( ( zoffset & 0xff00 ) != 0xb000 ) ) &&
               ( zoffset == -1 ) )
               {
               mtype = stat_mine;
               }
            else if ( !gamestate.BattleOptions.SpawnHealth )
               {
               return;
               }
            break;
         }
      }

 if (!firstemptystat)
	{temp = (statobj_t*)Z_LevelMalloc(sizeof(statobj_t),PU_LEVELSTRUCT,NULL);
	 //SoftError("\nMalloc-ing actor");
	 //if (insetupgame)
	  //	SoftError("in setup");
	}

 else
	{temp = lastemptystat;
	 //SoftError("\nfree actor available");
	 RemoveFromFreeStaticList(lastemptystat);
	}

 // Standard pole hack

 if ((zoffset>=14) && (zoffset<=17))
	 zoffset=-1;

 if (temp)
  {  memset(temp,0,sizeof(*temp));
	  temp->shapenum = stats[mtype].picnum;
	  temp->whichstat = statcount ++;
	  temp->tilex = tilex;
	  temp->tiley = tiley;
	  temp->x = ((long)tilex << TILESHIFT) + 0x8000;
	  temp->y = ((long)tiley << TILESHIFT) + 0x8000;
	  temp->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE;
	  temp->linked_to = -1;
	  if ((temp->areanumber<=0) || (temp->areanumber>NUMAREAS))
		  Error ("Sprite at x=%ld y=%ld type=%ld has an illegal areanumber\n",tilex,tiley,mtype);
     if ( mtype == stat_mine )
        {
        temp->z = nominalheight;
        }
     else if (zoffset!=-1)
		  {
		  if ((zoffset&0xff00)==0xb000)
           Set_NewZ_to_MapValue(&(temp->z),zoffset,"static",tilex,tiley);
		  else if (IsPlatform(tilex,tiley))
			  temp->z = PlatformHeight(tilex,tiley);
		  else if (zoffset==11)
			  temp->z=-65;
		  else if (zoffset==12)
			  temp->z=-66;
		  else
			  temp->z = nominalheight;
			 // Error ("You didn't specify a valid height over the sprite at tilex=%ld tiley=%ld\n",tilex,tiley);
		  }
	  else if (mtype>stat_chandelier)
		  temp->z = nominalheight;

	  temp->visspot = &spotvis[tilex][tiley];
	  temp->which = SPRITE;
	  temp->ticcount = stats[mtype].tictime;
	  temp->hitpoints = stats[mtype].hitpoints;
	  temp->itemnumber = stats[mtype].type;
     temp->flags = stats[mtype].flags;
	  temp->ammo = stats[mtype].ammo;
	  temp->numanims = stats[mtype].numanims;




     if (temp->flags & FL_BONUS)
		switch  (stats[mtype].type)
		  {case stat_lifeitem1:
			case stat_lifeitem2:
			case stat_lifeitem3:
			case stat_lifeitem4:
			 gamestate.treasuretotal++;
			 break;
		  }




      AddStatic(temp);

     onetimer = ((mtype == stat_rubble) || (mtype == stat_woodfrag) ||
                 (mtype == stat_metalfrag) || (mtype == stat_missmoke)
                );

     if (DoPanicMapping())
        {
        if (temp->numanims && (!onetimer))
           {
           temp->flags &= ~FL_ACTIVE;
           temp->numanims = 0;
           GameRandomNumber("SpawnStatic",mtype);
           }
        }

     else
        {
        if (temp->numanims)
           {
           if (!onetimer)
              temp->count = (int)(((int)GameRandomNumber("SpawnStatic",mtype) % stats[mtype].numanims) + 1);
           else
              temp->count = 0;
           }
        else if (temp->itemnumber == stat_standardpole)
           {
           if (MAPSPOT(temp->tilex,temp->tiley,2))
              temp->count = 2*(MAPSPOT(temp->tilex,temp->tiley,2)-14);
           else
              temp->count = 0;
           }

        if ((temp->itemnumber == stat_knifestatue) ||
            (temp->itemnumber == stat_emptystatue) ||
            (temp->itemnumber == stat_standardpole))
           temp->flags|=FL_ROTATING;
        }




     if (mtype != stat_missmoke)
		  sprites[tilex][tiley] = temp;
	  else
		  temp->flags |= FL_NONMARK;


//================ check special junk ==================================//

	  if (temp->itemnumber == stat_dariantouch)
		 {_2Dpoint *tdptr;

		  tdptr = &(MISCVARS->ETOUCH[MISCVARS->nexttouch]);

		  tdptr->x = tilex;
		  tdptr->y = tiley;
		  sprites[tilex][tiley]->linked_to = MISCVARS->nexttouch;
		  MISCVARS->nexttouch ++;
		 }
	  else if ((temp->itemnumber >= stat_touch1) &&
				  (temp->itemnumber <= stat_touch4))
		 {touchindices[tilex][tiley] = lasttouch + 1;
		  SD_PreCacheSoundGroup(SD_TOUCHPLATESND,SD_BADTOUCHSND);
		  lasttouch ++;
		 }

//=====================================================================//

     PreCacheStaticFrames(temp);

     PreCacheStaticSounds(temp->itemnumber);

	  if (temp->flags & FL_WEAPON)
		 MISCVARS->NUMWEAPONS ++;
  }
 else
	Error("Z_LevelMalloc failed in SpawnStatic!");

}

/*
===============
=
= SpawnInertStatic
=
===============
*/

void SpawnInertStatic (int x, int y, int z, int mtype)
{statobj_t * temp;




 if (!firstemptystat)
	{temp = (statobj_t*)Z_LevelMalloc(sizeof(statobj_t),PU_LEVELSTRUCT,NULL);
	 //SoftError("\nMalloc-ing actor");
	 //if (insetupgame)
	  //	SoftError("in setup");
	}

 else
	{temp = lastemptystat;
	 //SoftError("\nfree actor available");
	 RemoveFromFreeStaticList(lastemptystat);
	}

 if (temp)
  {  memset(temp,0,sizeof(*temp));
	  temp->shapenum = stats[mtype].picnum;

	  temp->whichstat = statcount ++;
	  temp->tilex = x>>16;
	  temp->tiley = y>>16;
	  temp->x = x;
	  temp->y = y;
	  temp->areanumber = MAPSPOT(temp->tilex,temp->tiley,0)-AREATILE;
	  temp->linked_to = -1;
	  if ((temp->areanumber<=0) || (temp->areanumber>NUMAREAS))
		  {
		  int tilex=temp->tilex;
		  int tiley=temp->tiley;

		  FindEmptyTile(&tilex,&tiley);
		  temp->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE;
		  }
	  temp->z=z;
	  temp->visspot = &spotvis[temp->tilex][temp->tiley];
	  temp->which = SPRITE;
	  temp->ticcount = stats[mtype].tictime;
	  temp->hitpoints = stats[mtype].hitpoints;
	  temp->itemnumber = stats[mtype].type;
	  temp->flags = (stats[mtype].flags|FL_ABP|FL_NONMARK);
     if (fog)
       {temp->shapenum++;
        temp->flags &= ~FL_TRANSLUCENT;
       }

     temp->ammo = stats[mtype].ammo;
	  temp->numanims = stats[mtype].numanims;
	  AddStatic(temp);
	  MakeStatActive(temp);
  }
 else
	Error("Z_LevelMalloc failed in SpawnStatic!");

}

/*
===============
=
= SpawnSolidStatic
=
===============
*/

void SpawnSolidStatic (statobj_t * temp)
{
	if (temp->flags & FL_ACTIVE)
	  temp->flags &= ~FL_ACTIVE;
	temp->hitpoints = INITIALFIRECOLOR;
   temp->flags = FL_SOLIDCOLOR|FL_SEEN|FL_ABP;
   if ((gamestate.BattleOptions.RespawnItems) &&
       (temp->itemnumber == stat_tntcrate)
      )
      temp->flags |= FL_RESPAWN;

   temp->ticcount = SOLIDCOLORTICTIME;
}


/*
======================
=
= PreCacheStaticSounds
=
======================
*/



void PreCacheStaticSounds (int itemnumber)
{

	if (stats[itemnumber].flags & FL_SHOOTABLE)
	  SD_PreCacheSound(SD_ITEMBLOWSND);


   switch(itemnumber)

      {
      case    stat_pit:
        SD_PreCacheSound(SD_PITTRAPSND);
        break;

      case    stat_bonusbarrel:
        SD_PreCacheSound(SD_BONUSBARRELSND);
        break;

      case    stat_knifestatue:
        SD_PreCacheSound(SD_GETKNIFESND);
        break;
      case    stat_gibs1:
      case    stat_gibs2:
      case    stat_gibs3:
         SD_PreCacheSound (SD_ACTORSQUISHSND);
         break;
      case    stat_pedgoldkey:
      case    stat_pedsilverkey:
      case    stat_pedironkey:
      case    stat_pedcrystalkey:
         SD_PreCacheSound (SD_GETKEYSND);

         break;
      case    stat_monkmeal:
         SD_PreCacheSound (SD_GETHEALTH1SND);
         break;
      case    stat_monkcrystal1:
         SD_PreCacheSound (SD_GETHEALTH2SND);
         break;
      case   stat_monkcrystal2:
         SD_PreCacheSound (SD_GETHEALTH2SND);
         break;
      case    stat_priestporridge:
         SD_PreCacheSound (SD_GETHEALTH1SND);
         SD_PreCacheSound(SD_COOKHEALTHSND);

         break;

      case   stat_healingbasin:
         SD_PreCacheSound (SD_GETHEALTH2SND);
         break;

      case stat_oneup:
         SD_PreCacheSound(SD_GET1UPSND);
         break;
      case stat_threeup:
         SD_PreCacheSound(SD_GET3UPSND);
         break;

      case stat_scotthead:
         SD_PreCacheSound(SD_GETHEADSND);
         break;

      case stat_twopistol:
      case stat_mp40:
      case stat_bazooka:
      case stat_firebomb:
      case stat_heatseeker:
      case stat_drunkmissile:
      case stat_firewall:
      case stat_splitmissile:
      case stat_kes:
         SD_PreCacheSound(SD_GETWEAPONSND);
         break;

      case stat_bat:
         SD_PreCacheSound(SD_GETBATSND);
         break;

      case stat_lifeitem1:
      case stat_lifeitem2:
      case stat_lifeitem3:
      case stat_lifeitem4:
         SD_PreCacheSound(SD_GETBONUSSND);
         break;


      case stat_random:
         SD_PreCacheSound(SD_GETGODSND);
         SD_PreCacheSound(SD_GETDOGSND);
         SD_PreCacheSound(SD_GETELASTSND);
         SD_PreCacheSound(SD_GETSHROOMSSND);
         SD_PreCacheSound(SD_LOSEMODESND);

         break;
      case stat_bulletproof:
         SD_PreCacheSound(SD_GETBVESTSND);
         SD_PreCacheSound(SD_LOSEMODESND);
         break;

      case stat_gasmask:
         SD_PreCacheSound(SD_GETMASKSND);
         SD_PreCacheSound(SD_LOSEMODESND);
         break;

      case stat_asbesto:
         SD_PreCacheSound(SD_GETAVESTSND);
         SD_PreCacheSound(SD_LOSEMODESND);
         break;

      case stat_elastic:
         SD_PreCacheSound(SD_GETELASTSND);
         SD_PreCacheSound(SD_LOSEMODESND);
         break;

      case stat_fleetfeet:
         SD_PreCacheSound(SD_GETFLEETSND);
         SD_PreCacheSound(SD_LOSEMODESND);
         break;

      case stat_godmode:
         SD_PreCacheSound(SD_GETGODSND);
         SD_PreCacheSound(SD_GODMODE1SND);

         break;

      case stat_dogmode:
         SD_PreCacheSound(SD_GETDOGSND);
         break;

      case stat_mushroom:
         SD_PreCacheSound(SD_GETSHROOMSSND);
         SD_PreCacheSound(SD_LOSEMODESND);

         break;

      case stat_dipball1:
      case stat_dipball2:
      case stat_dipball3:
         SD_PreCacheSound(SD_GETBONUSSND);
         break;

      default:
         SD_PreCacheSound(SD_GETBONUSSND);
         break;
      }

}





/*
===============
=
= SaveSwitches
=
===============
*/

void SaveSwitches(byte ** buffer, int * size)
{int numswitches,i;
 byte * tptr;

 numswitches = lastswitch-&switches[0];
 if (numswitches==0)
	 {
	 *size=0;
	 *buffer=SafeMalloc(16);
	 return;
	 }
 *size = numswitches*sizeof(wall_t);

 *buffer = (byte *)SafeMalloc(*size);
 tptr = *buffer;

 for(i=0;i<numswitches;i++)
  {memcpy(tptr,&switches[i],sizeof(wall_t));
	tptr += sizeof(wall_t);
  }

}


/*
===============
=
= LoadSwitches
=
===============
*/

void LoadSwitches (byte * buffer, int size)
{int numswitches,i,tilex,tiley;

 numswitches = size/sizeof(wall_t);

 for(i=0;i<numswitches;i++)
  {memcpy(&switches[i],buffer,sizeof(wall_t));
	tilex = switches[i].tilex;
	tiley = switches[i].tiley;
	actorat[tilex][tiley]=&switches[i];
	if (MAPSPOT(tilex,tiley,0) == 79) // On by default
      {
	   if (!(switches[i].flags & FL_ON))
         tilemap[tilex][tiley]--;
      }
   else if (switches[i].flags & FL_W_INVERTED) // Hi masked wall
      {
      maskedwallobj_t * lastmaskobj;

      lastmaskobj=maskobjlist[tilemap[tilex][tiley]&0x3ff];
    	if (switches[i].flags & FL_ON)
         lastmaskobj->toptexture++;
      }
	else if (switches[i].flags & FL_ON)
	   tilemap[tilex][tiley]++;
	buffer += sizeof(wall_t);
   touchindices[tilex][tiley] = lasttouch + 1;
	lasttouch ++;
  }
 lastswitch=&switches[numswitches];

}



/*
===============
=
= SpawnSwitchThingy
=
===============
*/

void SpawnSwitchThingy(int tilex, int tiley)
{
 lastswitch->flags |= FL_SWITCH;
 lastswitch->which = WALL;
 lastswitch->tilex = tilex;
 lastswitch->tiley = tiley;
 touchindices[tilex][tiley] = lasttouch + 1;
 lasttouch ++;
 actorat[tilex][tiley] = lastswitch;
 lastswitch ++;

}

/*
===============
=
= AnimateWalls
=
===============
*/

void AnimateWalls(void)
{
	int i;
	animwall_t * aw;

   if (DoPanicMapping()==true)
      return;

   for(i=0;i<MAXANIMWALLS;i++)
		{
		aw=&animwalls[i];
		if (aw->active==0)
			continue;
		if (aw->ticcount <= 0)
			{
			if (aw->count < animwallsinfo[i].numanims)
				{
				aw->texture = aw->basetexture + aw->count;
				aw->count++;
				}
			else
				{
				aw->texture = aw->basetexture;
				aw->count = 1;
				}

			while (aw->ticcount<=0)
				aw->ticcount+=animwallsinfo[i].tictime;
			}
		else
			aw->ticcount -= tics;
		}
}


#define M_ResetSprites(x)  \
  { if ((index == stat_dariantouch) && (!x->count))\
		 {x->shapenum = stats[index].picnum;               \
		  x->count = 1;                                     \
		  x->ticcount = stats[index].tictime;         \
		  x->flags &= ~FL_BACKWARDS;                   \
		  x->flags &= ~FL_ACTIVE;                       \
		 }                                               \
	}




void CheckCriticalStatics(void)
{respawn_t *rtemp,*ddt;
 int i,stilex,stiley;
 statobj_t*temp,*stat;

 for(rtemp = firstrespawn;rtemp;)
	{rtemp->ticcount --;
	 ddt = rtemp->next;

	 if (rtemp->ticcount <=0)
		 {int stype;

		  stilex = rtemp->tilex;
		  stiley = rtemp->tiley;

		  // if another weapon is there, nuke it
		  if (sprites[stilex][stiley])
			 {RemoveStatic(sprites[stilex][stiley]);
			  sprites[stilex][stiley] = NULL;
			 }

        if (rtemp->itemnumber == stat_tntcrate)
           {
           RemoveStatic((statobj_t*)(rtemp->linked_to));
           stype = stat_tntcrate;
           }
        else
           {
           for(i=0;i<NUMSTATS;i++)
              {
              if (rtemp->itemnumber == stats[i].type)
                 {
                 stype = i;
                 break;
                 }
              }

           }

		  SpawnStatic(stilex,stiley,stype,-1);
		  LASTSTAT->z = rtemp->spawnz;
		  LASTSTAT->flags |= FL_ABP;
		  MakeStatActive(LASTSTAT);
        SpawnNewObj(stilex,stiley,&s_itemspawn1,inertobj);
        SD_PlaySoundRTP(SD_RESPAWNSND,new->x,new->y);
		  new->flags |= FL_ABP;
		  MakeActive(new);
		  new->z = LASTSTAT->z;
		  RemoveRespawnStatic(rtemp);
		 }

	 rtemp = ddt;
	}

 for (temp = firstactivestat ; temp; )
	 {stat = temp->nextactive;

	  if (temp->flags & FL_SOLIDCOLOR)
		  {temp->ticcount--;
			if (temp->ticcount<=0)
				{temp->hitpoints+=SOLIDCOLORINCREMENT;
				 if (temp->hitpoints>MAXFIRECOLOR)
					 RemoveStatic(temp);
				 else
					 temp->ticcount = SOLIDCOLORTICTIME;
				}
		  }
	  temp = stat;
	 }


}



/*
===============
=
= DoSprites
=
===============
*/

void DoSprites(void)
{int index,i;
 statobj_t *temp,*tempnext;


#if (0)
	 Debug("\n");
#endif
i=0;
for(temp = firstactivestat;temp;)
  {tempnext = temp->nextactive;

	#if (0)
	 Debug("\nid: %d, shapenum: %d, numanims: %d",i++,temp->shapenum,temp->numanims);
	#endif

	if ((temp->shapenum != NOTHING) && (temp->flags & FL_ACTIVE))
		{index = temp->itemnumber;
		 temp->ticcount -= tics;
		 while (temp->ticcount <= 0)
			  {if (temp->count < temp->numanims)
					 {temp->shapenum = stats[index].picnum + temp->count;
					  if (index == stat_missmoke)
						  {RemoveStatic(temp);
							break;
						  }

					  if (((index == stat_rubble) && (temp->count == 9)) ||
							((index == stat_woodfrag) && (temp->count == 13)) ||
							((index == stat_metalfrag) && (temp->count == 9)))
						 {temp->flags &= ~FL_ACTIVE;
						  break;
						 }

					  if (temp->flags & FL_BACKWARDS)
						 {temp->count--;
						  M_ResetSprites(temp);
						 }
					  else
						 temp->count ++;
					 }
				else if (!(temp->flags & FL_BANDF))
					{temp->shapenum = stats[index].picnum;
					 temp->count=1;
					}
				else
					{temp->flags |= FL_BACKWARDS;
					 temp->count --;
					}
				temp->ticcount += stats[index].tictime;
			  }
		}
  temp = tempnext;

  }

}

void  SpawnStaticDamage(statobj_t * stat, int angle)
{
	GetNewActor ();
	MakeActive(new);
	NewState(new,&s_gunsmoke1);

	new->obclass = inertobj;
	new->which = ACTOR;
	new->x = (stat->x)-(costable[angle]>>4);
	new->y = (stat->y)+(sintable[angle]>>4);
	new->z = (stat->z)+stats[stat->itemnumber].heightoffset;
	new->drawx = new->x;
	new->drawy = new->y;
	new->tilex = (new->x >> TILESHIFT);
	new->tiley = (new->y >> TILESHIFT);
	new->dir = 0;
	new->speed = 0;
	new->flags = (FL_NEVERMARK|FL_ABP);
	if ((new->x<=0) || (new->y<=0))
	   Error("SpawnStaticDamage: bad x,y itemnumber=%ld\n",stat->itemnumber);
}
